package com.bicon.botu.mall.base.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bicon.botu.core.base.common.BusinessException;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.utils.IdGen;
import com.bicon.botu.core.base.common.utils.StringUtils;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.mall.base.common.BaseConstants;
import com.bicon.botu.mall.base.common.ValidationUtil;
import com.bicon.botu.mall.base.dto.FreightDispatchAreaDTO;
import com.bicon.botu.mall.base.dto.FreightTemplateDTO;
import com.bicon.botu.mall.base.dto.ProductDTO;
import com.bicon.botu.mall.base.entity.FreightDispatchArea;
import com.bicon.botu.mall.base.entity.FreightTemplate;
import com.bicon.botu.mall.base.mapper.FreightDispatchAreaMapper;
import com.bicon.botu.mall.base.mapper.FreightTemplateMapper;
import com.bicon.botu.mall.base.service.IFreightDispatchAreaService;
import com.bicon.botu.mall.base.service.IFreightTemplateService;
import com.bicon.botu.mall.base.vo.ProductVo;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;


/**
 * <p>
 * 运费模板 服务实现类
 * </p>
 *
 * @author liushujie
 * @since 2018-05-11
 */
@Slf4j
@Service
public class FreightTemplateServiceImpl extends ServiceImpl<FreightTemplateMapper, FreightTemplate> implements IFreightTemplateService {

    @Autowired
    IFreightDispatchAreaService iFreightDispatchAreaService;

    @Autowired
    FreightDispatchAreaMapper freightDispatchAreaMapper;

    @Autowired
    private RedisHandler redisHandler;

    /**
     * 新增运费模板
     *
     * @param freightTemplateDTO 运费模板DTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public boolean insert(FreightTemplateDTO freightTemplateDTO) {
        log.info("【******运费模板，新增运费模板开始******】");
        //1先创建运费模板
        FreightTemplate freightTemplate = new FreightTemplate();
        freightTemplate.preInsert();
        freightTemplate.setTenantId(IdGen.uuid());
        freightTemplate.setName(freightTemplateDTO.getName());
        freightTemplate.setEnable(freightTemplateDTO.getEnable());
        freightTemplate.setValuationStatus(freightTemplateDTO.getValuationStatus());
        if(ValidationUtil.isEmpty(freightTemplateDTO.getSort())){
            freightTemplate.setSort(0);
        }else{
            freightTemplate.setSort(freightTemplateDTO.getSort());
        }
        //2 根据运费模板id 创建配送区域模板
        List<FreightDispatchArea> freightDispatchAreaList = new ArrayList<>();
        for (FreightDispatchAreaDTO freightDispatchAreaDTO : freightTemplateDTO.getFreightDispatchAreaList()) {
            FreightDispatchArea freightDispatchArea = new FreightDispatchArea();
            BeanUtils.copyProperties(freightDispatchAreaDTO, freightDispatchArea);
            freightDispatchArea.preInsert();
            //运费模板id
            freightDispatchArea.setFreightTemplateId(freightTemplate.getId());
            freightDispatchArea.setTenantId(freightTemplate.getTenantId());
            freightDispatchAreaList.add(freightDispatchArea);
        }

        boolean flag = false;
        if (freightTemplate.insert()) {
            log.info("【******运费模板，新增运费模板入库成功******】,运费模板ID:" + freightTemplate.getId());
            flag = iFreightDispatchAreaService.insertBatch(freightDispatchAreaList);
            log.info("【******运费模板，新增运费模板，批量配送区域入库******】:" + flag);
            if (!flag) {
                //批量失败
                throw new BusinessException(Constants.RESPONSE_CODE_500, Constants.RESPONSE_MESSAGE_500);
            }
        }
        return flag;
    }

    /**
     * 修改运费模板
     *
     * @param freightTemplateDTO 运费模板DTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public boolean update(FreightTemplateDTO freightTemplateDTO) {
        log.info("【******运费模板，修改运费模板开始******】，运费模板ID：" + freightTemplateDTO.getId());
        //1更新运费模板
        FreightTemplate freightTemplate = new FreightTemplate();
        freightTemplate.preUpdate();
        freightTemplate.setId(freightTemplateDTO.getId());
        freightTemplate.setName(freightTemplateDTO.getName());
        if (!StringUtils.isEmpty(freightTemplateDTO.getEnable())) {
            freightTemplate.setEnable(freightTemplateDTO.getEnable());
        }
        if (!StringUtils.isEmpty(freightTemplateDTO.getValuationStatus())) {
            freightTemplate.setValuationStatus(freightTemplateDTO.getValuationStatus());
        }
        if (!StringUtils.isEmpty(freightTemplateDTO.getSort())) {
            freightTemplate.setSort(freightTemplateDTO.getSort());
        }
        boolean flag = freightTemplate.updateById();
        if (!flag) {
            return flag;
        }
        //区域列表为空，直接返回，不修改子集
        if (ValidationUtil.isEmpty(freightTemplateDTO.getFreightDispatchAreaList())) {
            return flag;
        }
        //2根据运费id删除运费模板配送区域列表
        EntityWrapper<FreightDispatchArea> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("freight_template_id", freightTemplateDTO.getId());
        freightDispatchAreaMapper.delete(entityWrapper);
        //3批量插入运费模板
        List<FreightDispatchArea> freightDispatchAreaList = new ArrayList<>();
        for (FreightDispatchAreaDTO freightDispatchAreaDTO : freightTemplateDTO.getFreightDispatchAreaList()) {
            FreightDispatchArea freightDispatchArea = new FreightDispatchArea();
            BeanUtils.copyProperties(freightDispatchAreaDTO, freightDispatchArea);
            freightDispatchArea.preInsert();
            //运费模板id
            freightDispatchArea.setFreightTemplateId(freightTemplate.getId());
            freightDispatchArea.setTenantId(freightTemplateDTO.getTenantId());
            freightDispatchAreaList.add(freightDispatchArea);
        }
        return iFreightDispatchAreaService.insertBatch(freightDispatchAreaList);
    }

    /**
     * 计算运费
     * 1、根据商品获取运费模板，根据运费模板获取对应商品收货地址的运费资费。
     * 2、根据商品列表区域资费列表，计算总运费。
     *
     * @param productDTOList 商品信息列表
     * @param addressId      收货地址id
     * @return
     */
    @Override
    public BigDecimal calcFreight(List<ProductDTO> productDTOList, String addressId) {
        //资费列表
        List<FreightDispatchArea> freightDispatchAreaList = new ArrayList<>();
        //商品列表
        List<ProductVo> productVoList = new ArrayList<>();

        List<Integer> valuationStatusList = new ArrayList<>();
        //初始运费
        BigDecimal c = new BigDecimal("0.00");
        for (int i = 0; i < productDTOList.size(); i++) {
            //1、根据商品获取运费模板，根据运费模板获取对应商品收货地址的运费资费。
            Map<Object, Object> map = getFreightByProduct(productDTOList.get(i), addressId);
            //商品对象
            productVoList.add((ProductVo) map.get("product"));
            //计费方式
            valuationStatusList.add((Integer) map.get("valuationStatus"));
            //区域资费
            freightDispatchAreaList.add((FreightDispatchArea) map.get("freightDispatchArea"));
        }
        if (freightDispatchAreaList.size() == 0 || productVoList.size() == 0) {
            //资费为空或者商品对象为空，返回包邮价格0.00
            return c;
        }
        //2、根据商品列表区域资费列表，计算总运费
        if (productDTOList.size() == 1) {
            //单个商品计算
            c = calcSingleFreight(productDTOList, productVoList, freightDispatchAreaList, valuationStatusList);
        } else {
            //多个商品运费相加计算
            c = calcMultiFreight(productDTOList, productVoList, freightDispatchAreaList, valuationStatusList);
        }
        return c.setScale(2, BigDecimal.ROUND_UP);
    }


    /**
     * 根据商品信息和收货地址获取对应的资费对象
     *
     * @param productDTO 商品对象
     * @param addressId  收货地址
     * @return 资费对象
     */
    private Map<Object, Object> getFreightByProduct(ProductDTO productDTO, String addressId) {
        Map<Object, Object> map = new HashMap<Object, Object>();
        //区域资费默认包邮对象
        FreightDispatchArea freightDispatchArea = new FreightDispatchArea();
        ProductVo productVoDeaf = new ProductVo();
        freightDispatchArea.setPinkage(1);
        freightDispatchArea.setFreight(new BigDecimal("0"));
        //缓存获取商品信息【注意：是1库，不是全局0库】
        String product = redisHandler.getLocalRedisTemplate().getStringValue(BaseConstants.PRODUCT_INFO, productDTO.getProductId());
        //后期订单收货地址将收货地址放入缓存中，从缓存获取地址信息
        if (ValidationUtil.isEmpty(product)) {
            //获取商品对象为空
            log.info("【******商品运费计算，获取商品对象为空******】，商品ID：" + productDTO.getProductId());
            map.put("freightDispatchArea", freightDispatchArea);
            map.put("product", productVoDeaf);
            map.put("valuationStatus", 0);
            return map;
        }
        ProductVo productVo = JSONObject.parseObject(product, ProductVo.class);
        //运费模板id {如果是0，包邮，无运费}
        if (!ValidationUtil.isEmpty(productVo)) {
            if (ValidationUtil.equals(productVo.getIsFreeFreight(), "0")) {
                //如果包邮，直接返回资费对象
                map.put("freightDispatchArea", freightDispatchArea);
                map.put("product", productVo);
                map.put("valuationStatus", 0);
                return map;
            }
            //根据运费模板ID，获取运费计价方式[条件：模板id，启用，未删除]
            //计价方式(1件数，2重量，3体积)
            FreightTemplate freightTemplate = new FreightTemplate().selectOne(new EntityWrapper<>().eq("id", productVo.getIsFreeFreight())
                    .eq("enable", 0).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));

            if (ValidationUtil.isEmpty(freightTemplate)) {
                //未查到运费模板，则返回资费对象，包邮
                map.put("freightDispatchArea", freightDispatchArea);
                map.put("product", productVo);
                map.put("valuationStatus", 0);
                return map;
            }
            map.put("valuationStatus", freightTemplate.getValuationStatus());
            //根据运费模板id 获取模板区域list
            List<FreightDispatchArea> freightDispatchAreaList = new FreightDispatchArea().selectList(new EntityWrapper<>().eq("freight_template_id", productVo.getIsFreeFreight())
                    .eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
            if (ValidationUtil.isEmpty(freightDispatchAreaList)) {
                //资费区域list为空
                map.put("freightDispatchArea", freightDispatchArea);
                map.put("product", productVo);
                return map;
            }
            //默认资费
            FreightDispatchArea freightDispatchAreaDefaults = null;
            //根据收货地点的省份 匹配运费资费区域list
            for (FreightDispatchArea freightDispatchArea1 : freightDispatchAreaList) {
                //首先取出默认的资费  是否默认(0:否;1:是)
                if (ValidationUtil.equals(freightDispatchArea1.getDefaults(), 1)) {
                    freightDispatchAreaDefaults = freightDispatchArea1;
                }
                //在匹配收货地址的资费
                if (freightDispatchArea1.getName().indexOf(addressId) != -1) {
                    //匹配到，则返回对应的资费
                    map.put("freightDispatchArea", freightDispatchArea1);
                    map.put("product", productVo);
                    return map;
                }
            }
            //没有匹配到 返回通用默认资费
            if (!ValidationUtil.isEmpty(freightDispatchAreaDefaults)) {
                map.put("freightDispatchArea", freightDispatchAreaDefaults);
                map.put("product", productVo);
                return map;
            }
        } else {
            //空，资费为包邮
            map.put("freightDispatchArea", freightDispatchArea);
            map.put("product", productVoDeaf);
            map.put("valuationStatus", 0);
        }
        return map;
    }


    /**
     * 根据商品列表区域资费列表，多件商品 计算总运费
     *
     * @param productDTOList          原始商品list 以及购买商品数量
     * @param productVoList           商品对象，体积、重量等信息
     * @param freightDispatchAreaList 运费资费区域列表
     * @param valuationStatusList     计价方式
     * @return 商品列表总运费
     */
    private BigDecimal calcSingleFreight(List<ProductDTO> productDTOList, List<ProductVo> productVoList, List<FreightDispatchArea> freightDispatchAreaList, List<Integer> valuationStatusList) {
        //#TODO
        //1、商品的运费模板id（0:包邮 ，uuid:选择运费模板 ）
        //2、根据收货地址匹配此运费模板中配送区域
        //2.1 检查此运费模板中是否有送货地址的区域（省份名称）
        //2.2 若是没有，则去该模板中的默认区域
        //2.3 检查配送区域是否开启包邮规则
        //2.4 若是没有开启，则按照 计算公式来计算
        //2.5 若是开启，则看是否满足规则条件，不满足 返回2.4
        //单件商品计算规则：【 首件首费、续件续费、不足整件按整件计算】
        log.info("【******商品运费计算，单件商品运费计算开始******】");
        //包邮默认运费
        BigDecimal singleFreight = new BigDecimal("0.00");
        //计价方式
        Integer valuationStatus = valuationStatusList.get(0);
        if (ValidationUtil.equals(valuationStatus, 0)) {
            //计价方式如果是0，是上一步设置的，返回包邮
            return singleFreight;
        }
        FreightDispatchArea freightDispatchArea = freightDispatchAreaList.get(0);
        if (freightDispatchArea.getPinkage().equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_PINKAGERULE1)) {
            //检查包邮规则
            if (ValidationUtil.isEmpty(freightDispatchArea.getPinkageRule()) && ValidationUtil.isEmpty(freightDispatchArea.getPinkageValue())) {
                //如果为空，是代表没有找到资费模板，上一步已做处理
                //规则为空，包邮[Rule&Value]
                return singleFreight;
            }

            //根据计价方式来算【计价方式valuationStatus (1件数，2重量，3体积)】
            //包邮规则(1价格、2、件数 、3、重量、4、体积)
            if (ValidationUtil.equals(valuationStatus, BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE1)) {
                //1、按件数， pinkageRule包邮规则为：1价格、2件数
                //规则不为空，检查是否满足规则
                if (freightDispatchArea.getPinkageRule().equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_PINKAGERULE2)) {
                    log.info("【******商品运费计算，检查是否包邮，按件数计算******】，商品包邮规则值：" + freightDispatchArea.getPinkageValue());
                    //如果是按件数
                    if (productDTOList.get(0).getNumber() >= Integer.valueOf(freightDispatchArea.getPinkageValue())) {
                        //购买数量大于等于条件，则包邮免运费
                        return singleFreight;
                    } else {
                        //按照资费计算【 首件首费、续件续费、不足整件按整件计算】
                        if (productDTOList.get(0).getNumber() > freightDispatchArea.getFirstPart()) {
                            //购买数量大于 首件值 计算
                            //首件资费+续件资费【续件资费*(购买数量/续件)】
                            return calcFreight(productDTOList.get(0).getNumber(), freightDispatchArea, productVoList, valuationStatus);
                        } else {
                            //购买数量 不足首件值，直接返回，首件资费
                            return freightDispatchArea.getFreight();
                        }
                    }
                }

            } else if (ValidationUtil.equals(valuationStatus, BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE2)) {
                //2、按重量， pinkageRule包邮规则为：1价格、3 重量
                //规则不为空，检查是否满足规则
                if (freightDispatchArea.getPinkageRule().equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_PINKAGERULE3)) {
                    log.info("【******商品运费计算，检查是否包邮，按重量计算******】，商品包邮规则值：" + freightDispatchArea.getPinkageValue());
                    //如果是按重量，商品数量*商品重量
                    if (productDTOList.get(0).getNumber() * productVoList.get(0).getWeight() >= Double.valueOf(freightDispatchArea.getPinkageValue())) {
                        //购买数量大于等于条件，则包邮免运费
                        return singleFreight;
                    } else {
                        //按照资费计算【 首件首费、续件续费、不足整件按整件计算】
                        if (productDTOList.get(0).getNumber() * productVoList.get(0).getWeight() > freightDispatchArea.getFirstPart()) {
                            //购买商品重量 大于 首件值 计算
                            //首件资费+续件资费【续件资费*(购买数量/续件)】
                            return calcFreight(productDTOList.get(0).getNumber(), freightDispatchArea, productVoList, valuationStatus);
                        } else {
                            //购买重量 不足首件值重量，直接返回，首件资费
                            return freightDispatchArea.getFreight();
                        }
                    }
                }
            } else {
                //3、按体积， pinkageRule包邮规则为：1价格、4 体积
                //规则不为空，检查是否满足规则
                if (freightDispatchArea.getPinkageRule().equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_PINKAGERULE4)) {
                    log.info("【******商品运费计算，检查是否包邮，按体积计算******】，商品包邮规则值：" + freightDispatchArea.getPinkageValue());
                    //如果是按体积，商品数量*商品体积
                    if (productDTOList.get(0).getNumber() * productVoList.get(0).getVolume() >= Double.valueOf(freightDispatchArea.getPinkageValue())) {
                        //购买数量大于等于条件，则包邮免运费
                        return singleFreight;
                    } else {
                        //按照资费计算【 首件首费、续件续费、不足整件按整件计算】
                        if (productDTOList.get(0).getNumber() * productVoList.get(0).getVolume() > freightDispatchArea.getFirstPart()) {
                            //购买商品重量 大于 首件值 计算
                            //首件资费+续件资费【续件资费*(购买数量/续件)】
                            return calcFreight(productDTOList.get(0).getNumber(), freightDispatchArea, productVoList, valuationStatus);
                        } else {
                            //购买重量 不足首件值重量，直接返回，首件资费
                            return freightDispatchArea.getFreight();
                        }
                    }
                }

            }
            //每个计价方式都有 价格包邮规则
            //通用规则，按价格处理
            if (freightDispatchArea.getPinkageRule().equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_PINKAGERULE1)) {
                log.info("【******商品运费计算，检查是否包邮******】，商品包邮规则值：" + freightDispatchArea.getPinkageValue());
                //按价格
                //商品显示价格  商品单价*商品数量
                BigDecimal value1 = productVoList.get(0).getProductPrice().multiply(new BigDecimal(String.valueOf(productDTOList.get(0).getNumber())));
                //包邮规则 价格值
                BigDecimal value2 = new BigDecimal(String.valueOf(freightDispatchArea.getPinkageValue()));
                //比大小
                if (value1.compareTo(value2) == 1) {
                    //大于规则 包邮
                    return singleFreight;
                } else if (value1.compareTo(value2) == -1) {
                    //小于规则  按照资费计算【 首件首费、续件续费、不足整件按整件计算】
                    return calcFreight(productDTOList.get(0).getNumber(), freightDispatchArea, productVoList, valuationStatus);
                } else {
                    //等于规则 包邮
                    return singleFreight;
                }
            }

        } else {
            //不包邮，直接按照计价方式，商品属性、购买数量计算
            return calcFreight(productDTOList.get(0).getNumber(), freightDispatchArea, productVoList, valuationStatus);
        }
        return singleFreight;
    }


    /**
     * 根据商品列表区域资费列表，多件商品 计算总运费
     *
     * @param productDTOList          原始商品list 以及购买商品数量
     * @param productVoList           商品对象，体积、重量等信息
     * @param freightDispatchAreaList 运费资费区域列表
     * @param valuationStatusList     计价方式
     * @return 商品列表总运费
     */
    private BigDecimal calcMultiFreight(List<ProductDTO> productDTOList, List<ProductVo> productVoList, List<FreightDispatchArea> freightDispatchAreaList, List<Integer> valuationStatusList) {
        //1、商品的运费模板id（0:包邮 ，uuid:选择运费模板 ）
        //2、根据收货地址匹配此运费模板中配送区域
        //2.1 检查此运费模板中是否有送货地址的区域（省份名称）
        //2.2 若是没有，则去该模板中的默认区域
        //2.3 检查配送区域是否开启包邮规则
        //2.4 若是没有开启，则按照 计算公式来计算
        //2.5 若是开启，则看是否满足规则条件，不满足 返回2.4
        //多件商品 运费计算,计算规则【取最大首费，取最小增费】，作为首费
        //排序list
        List<FreightDispatchArea> freightDispatchAreaListSort = freightDispatchAreaList;
        //根据首费排序资费list
        Collections.sort(freightDispatchAreaListSort, new Comparator<FreightDispatchArea>() {
            @Override
            public int compare(FreightDispatchArea f1, FreightDispatchArea f2) {
                //按照首费进行升序排列  value1.compareTo(value2)
                if (f1.getFreight().compareTo(f2.getFreight()) == 1) {
                    //大于
                    return 1;
                }
                if (f1.getFreight().compareTo(f2.getFreight()) == 0) {
                    //等于
                    return 0;
                }
                //小于
                return -1;
            }
        });
        BigDecimal freight = new BigDecimal("0.00");
        //最大首费对象
        FreightDispatchArea fistFreightFreightDispatchArea = freightDispatchAreaListSort.get(freightDispatchAreaListSort.size() - 1);
        //最大首费值
        BigDecimal maxFirstfreight = fistFreightFreightDispatchArea.getFreight();
        //开始计算所有的商品运费
        for (int i = 0; i < productDTOList.size(); i++) {

            if (ValidationUtil.isEmpty(freightDispatchAreaList.get(i).getFreightTemplateId()) && freightDispatchAreaList.get(i).getPinkage() == 1) {
                //该商品为包邮
                freight = freight.add(new BigDecimal("0.00"));
                continue;
            }
            //运费模板不为空，说明有资费对应的区域资费情况
            if (!ValidationUtil.isEmpty(freightDispatchAreaList.get(i).getFreightTemplateId())) {
                //有配送区域
                if (ValidationUtil.equals(freightDispatchAreaList.get(i).getFreightTemplateId(), fistFreightFreightDispatchArea.getFreightTemplateId())) {
                    //当与最大资费对象的id相等，取首费
                    freight = freight.add(maxFirstfreight);
                    continue;
                }

                //检查计价方式是否为0
                if (ValidationUtil.equals(valuationStatusList.get(i), 0)) {
                    //计价方式如果是0，是上一步设置的，返回改件商品包邮
                    freight = freight.add(new BigDecimal("0.00"));
                    continue;
                }

                //不相等则计算费用
                //首先 判断是否有包邮规则
                if (freightDispatchAreaList.get(i).getPinkage() == 1) {
                    //检查包邮规则
                    if (ValidationUtil.isEmpty(freightDispatchAreaList.get(i).getPinkageValue()) && ValidationUtil.isEmpty(freightDispatchAreaList.get(i).getPinkageRule())) {
                        //规则为空，包邮  rule&value
                        freight = freight.add(new BigDecimal("0.00"));
                        continue;
                    }
                    //这里需要根据包邮的规则来判断计价
                    //根据计价方式来算【计价方式valuationStatus (1件数，2重量，3体积)】
                    //包邮规则(1价格、2、件数 、3、重量、4、体积)
                    if (ValidationUtil.equals(valuationStatusList.get(i), BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE1)) {
                        //1、按件数， pinkageRule包邮规则为：1价格、2件数
                        //规则不为空，检查是否满足规则
                        if (freightDispatchAreaList.get(i).getPinkageRule() == 2) {
                            log.info("【******商品运费计算，检查是否包邮******】，商品包邮规则值：" + freightDispatchAreaList.get(i).getPinkageValue());
                            //如果是按件数
                            if (productDTOList.get(i).getNumber() >= Integer.valueOf(freightDispatchAreaList.get(i).getPinkageValue())) {
                                //购买数量大于等于条件，则包邮免运费
                                freight = freight.add(new BigDecimal("0.00"));
                                continue;
                            } else {
                                //直接按照资费计算  商品信息、区域资费信息、计价方式
                                freight = freight.add(calcSequenceFreight(productDTOList.get(i).getNumber(), freightDispatchAreaList.get(i), productVoList.get(i), valuationStatusList.get(i)));
                                continue;
                            }
                        }
                    } else if (ValidationUtil.equals(valuationStatusList.get(i), BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE2)) {
                        //2、按重量， pinkageRule包邮规则为：1价格、3 重量
                        //规则不为空，检查是否满足规则
                        if (freightDispatchAreaList.get(i).getPinkageRule() == 3) {
                            log.info("【******商品运费计算，检查是否包邮，按重量计算******】，商品包邮规则值：" + freightDispatchAreaList.get(i).getPinkageValue());
                            //如果是按重量，商品数量*商品重量
                            if (productDTOList.get(i).getNumber() * productVoList.get(i).getWeight() >= Double.valueOf(freightDispatchAreaList.get(i).getPinkageValue())) {
                                //购买数量大于等于条件，则包邮免运费
                                freight = freight.add(new BigDecimal("0.00"));
                                continue;
                            } else {
                                //直接按照资费计算
                                freight = freight.add(calcSequenceFreight(productDTOList.get(i).getNumber(), freightDispatchAreaList.get(i), productVoList.get(i), valuationStatusList.get(i)));
                                continue;
                            }
                        }
                    } else {
                        //3、按体积， pinkageRule包邮规则为：1价格、4 体积
                        //规则不为空，检查是否满足规则
                        if (freightDispatchAreaList.get(i).getPinkageRule() == 4) {
                            log.info("【******商品运费计算，检查是否包邮，按体积计算******】，商品包邮规则值：" + freightDispatchAreaList.get(i).getPinkageValue());
                            //如果是按重量，商品数量*商品重量
                            if (productDTOList.get(i).getNumber() * productVoList.get(i).getVolume() >= Double.valueOf(freightDispatchAreaList.get(i).getPinkageValue())) {
                                //购买数量大于等于条件，则包邮免运费
                                freight = freight.add(new BigDecimal("0.00"));
                                continue;
                            } else {
                                //直接按照资费计算
                                freight = freight.add(calcSequenceFreight(productDTOList.get(i).getNumber(), freightDispatchAreaList.get(i), productVoList.get(i), valuationStatusList.get(i)));
                                continue;
                            }
                        }

                    }
                    //通用规则，按价格处理
                    //规则不为空，检查是否满足规则
                    if (freightDispatchAreaList.get(i).getPinkageRule() == 1) {
                        log.info("【******商品运费计算，检查是否包邮，包邮按价格计算******】，商品包邮规则值：" + freightDispatchAreaList.get(i).getPinkageValue());
                        //按价格
                        //商品显示价格  商品单价*商品数量
                        BigDecimal value1 = productVoList.get(i).getProductPrice().multiply(new BigDecimal(String.valueOf(productDTOList.get(i).getNumber())));
                        //包邮规则 价格值
                        BigDecimal value2 = new BigDecimal(String.valueOf(freightDispatchAreaList.get(i).getPinkageValue()));
                        //比大小
                        if (value1.compareTo(value2) == 1) {
                            //大于规则 包邮
                            freight = freight.add(new BigDecimal("0.00"));
                            continue;
                        } else if (value1.compareTo(value2) == -1) {
                            //小于规则  按照资费计算【 首件首费、续件续费、不足整件按整件计算】
                            freight = freight.add(calcSequenceFreight(productDTOList.get(i).getNumber(), freightDispatchAreaList.get(i), productVoList.get(i), valuationStatusList.get(i)));
                            continue;
                        } else {
                            //等于规则 包邮
                            freight = freight.add(new BigDecimal("0.00"));
                            continue;
                        }
                    }
                } else {
                    //不包邮  直接按照规则计算
                    log.info("【******商品运费计算，不包邮计算******】*****************");
                    freight = freight.add(calcSequenceFreight(productDTOList.get(i).getNumber(), freightDispatchAreaList.get(i), productVoList.get(i), valuationStatusList.get(i)));
                    continue;
                }


            }
        }
        return freight;
    }

    /**
     * 计算单个商品资费
     *
     * @param number              商品数量
     * @param freightDispatchArea 资费对象
     * @param productVoList       商品对象
     * @param valuationStatus     计价方式
     * @return
     */
    private BigDecimal calcFreight(Integer number, FreightDispatchArea freightDispatchArea, List<ProductVo> productVoList, Integer valuationStatus) {
        BigDecimal baseSequel = new BigDecimal("0");
        BigDecimal sequelFreight = new BigDecimal("0");
        BigDecimal singleFreight = new BigDecimal("0");
        //计价方式(1件数，2重量，3体积)
        if (valuationStatus.equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE2)) {
            //重量,续费基数
            baseSequel = new BigDecimal(String.valueOf(number * productVoList.get(0).getWeight() / freightDispatchArea.getSequelPart()));
            //续件费用
            sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
            //首件资费+续件资费【续件资费*(购买数量*商品体积/续件重量)】
            singleFreight = freightDispatchArea.getFreight().add(sequelFreight);
        } else if (valuationStatus.equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE3)) {
            //体积
            //重量,续费基数
            baseSequel = new BigDecimal(String.valueOf(number * productVoList.get(0).getVolume() / freightDispatchArea.getSequelPart()));
            //续件费用
            sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
            //首件资费+续件资费【续件资费*(购买数量*商品体积/续件重量)】
            singleFreight = freightDispatchArea.getFreight().add(sequelFreight);
        } else {
            //件数
            //购买数量-首件数量  如果大于 则计算续费，小于等于直接用首件的资费就行
            if((number-freightDispatchArea.getFirstPart()) >0){
                //判断续件数量
                if((number-freightDispatchArea.getFirstPart()>= freightDispatchArea.getSequelPart())){
                    baseSequel = new BigDecimal(String.valueOf(number-freightDispatchArea.getFirstPart()));
                    sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
                    singleFreight = freightDispatchArea.getFreight().add(sequelFreight);
                }else{
                    //不满足 则继续按照 首费使用
                    singleFreight = freightDispatchArea.getFreight();
                }
            }else{
                singleFreight = freightDispatchArea.getFreight();
            }

//            //续费基数
//            baseSequel = new BigDecimal(String.valueOf(number / freightDispatchArea.getSequelPart()));
//            //续件费用
//            sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
//            //单件商品 运费
//            singleFreight = freightDispatchArea.getFreight().add(sequelFreight);
        }
        log.info("【******商品运费计算，单件商品运费计算结束******】，运费为：" + singleFreight.toString());
        return singleFreight;
    }

    /**
     * 计算续件费用
     * 续费基数
     * 首件资费+续件资费【续件资费*(购买数量/续件)】
     *
     * @param number              商品数量
     * @param freightDispatchArea 资费对象
     * @param productVo           商品对象
     * @param valuationStatus     计价方式
     * @return
     */
    private BigDecimal calcSequenceFreight(Integer number, FreightDispatchArea freightDispatchArea, ProductVo productVo, Integer valuationStatus) {
        BigDecimal baseSequel = new BigDecimal("0");
        BigDecimal sequelFreight = new BigDecimal("0");
        log.info("【******商品运费计算，单件商品运费计算结束******】，续件运费为：" + sequelFreight);
        if (valuationStatus.equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE2)) {
            //重量,续费基数
            baseSequel = new BigDecimal(String.valueOf(number * productVo.getWeight() / freightDispatchArea.getSequelPart()));
            //续件费用
            sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
        } else if (valuationStatus.equals(BaseConstants.BOTU_MALL_BASE_FREIGHT_VALUATION_TYPE3)) {
            //体积
            baseSequel = new BigDecimal(String.valueOf(number * productVo.getVolume() / freightDispatchArea.getSequelPart()));
            //续件费用
            sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
        } else {

            //件数
            //购买数量-首件数量  如果大于 则计算续费，小于等于直接用首件的资费就行
            if((number-freightDispatchArea.getFirstPart()) >0){
                //判断续件数量
                if((number-freightDispatchArea.getFirstPart()>=freightDispatchArea.getSequelPart())){
                    baseSequel = new BigDecimal(String.valueOf(number-freightDispatchArea.getFirstPart()));
                    sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
//                    singleFreight = freightDispatchArea.getFreight().add(sequelFreight);
                }else{
                    //不满足 则继续按照 首费使用
                    sequelFreight =  new BigDecimal("0");
                }
            }else{
                sequelFreight =  new BigDecimal("0");
            }
            //件数
            //续费基数
//            baseSequel = new BigDecimal(String.valueOf(number / freightDispatchArea.getSequelPart()));
//            //续件费用
//            sequelFreight = freightDispatchArea.getSequelFreight().multiply(baseSequel);
        }
        return sequelFreight;
    }


}
